package com.azt.provider.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.azt.api.pojo.LevelRecord;
import com.azt.api.pojo.LevelRule;
import com.azt.api.service.LevelService;
import com.azt.provider.mapper.LevelRecordMapper;
import com.azt.provider.mapper.LevelRuleMapper;
import com.azt.provider.mapper.LevelUserMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import static com.azt.utils.Preconditions.checkArgument;

/**
 * 成长值管理
 * Created by LiQZ on 2017/4/12.
 */
@Service
public class LevelServiceImpl implements LevelService {

    private static final Logger logger = LoggerFactory.getLogger(LevelServiceImpl.class);

    @Autowired
    private LevelRecordMapper levelRecordMapper;

    @Autowired
    private LevelUserMapper levelUserMapper;

    @Autowired
    private LevelRuleMapper levelRuleMapper;

    /**
     * 变更成长值
     * @param parentId 总公司 ID
     * @param type 1 采购商 2 供应商
     * @param value value > 0 增加，value < 0 减少
     * @param reason 变更原因
     */
    public void addAmount(Integer ruleId, Integer parentId, Integer type, Integer value, String reason) {
        logger.info("company {} type {} value add {} reason {}", parentId, type, value, reason);
        if (type == null) {
            return;
        }

        // 查询一下，如果不存在初始化
        Integer before = levelUserMapper.selectValue(parentId, type);
        if (before == null) {
            levelUserMapper.insertInit(parentId);
            before = 0;
        }
        // 更新总成长值
        int result = levelUserMapper.updateValue(parentId, type, value);
        checkArgument(result != 0, "增加成长值失败");
        // 增加记录
        LevelRecord record = new LevelRecord();
        record.setType(value > 0 ? 1: -1);
        record.setChangeReason(reason);
        record.setAfterValue(before + value);
        record.setChangeValue(Math.abs(value));
        record.setCompanyId(parentId);
        record.setLevelType(type);
        record.setRuleId(ruleId);
        levelRecordMapper.insert(record);
        logger.info("parentId {} add value {} last value {}", parentId, value, record.getAfterValue());
    }

    private Integer findParentId(Integer companyId) {
        Integer parentId = null;
        Integer lastParentId = companyId;
        while (lastParentId != null) {
            parentId = lastParentId;
            lastParentId = levelUserMapper.selectParentCompany(lastParentId);
        }
        return parentId;
    }

    @Override
    public void updateLevel(Integer companyId, Integer type, String ruleCode) {
        // 增加异常捕获，防止锚点影响正常逻辑
        logger.info("begin add level amount, companyId {} type {} ruleCode {}", companyId, type, ruleCode);
        try {
            updateLevel0(companyId, type, ruleCode);
        } catch (Exception e) {
            logger.error("add level amount fail, companyId {} type {} ruleCode {}", companyId, type, ruleCode);
            e.printStackTrace();
        }
        logger.info("add level amount success, companyId {} type {} ruleCode {}", companyId, type, ruleCode);
    }

    private void updateLevel0(Integer companyId, Integer type, String ruleCode) {
        // 第一件事就是切换到主公司 id
        Integer parentId = findParentId(companyId);
        logger.info("change companyId {} to parent companyId {}", companyId, parentId);
        // 查询规则
        LevelRule rule = levelRuleMapper.selectByCode(ruleCode);
        if (rule == null) {
            logger.info("add company {} fail, level rule code {} is not exist", parentId, ruleCode);
            return;
        }
        // 判断规则限制
        String limitRule = rule.getLimitRule();
        if (!meetTheRules(rule.getId(), limitRule, parentId)) {
            // 不符合规则就不加成长值
            logger.info("add company {} fail, it is not meet rule.", parentId);
            return;
        }
        // 给用户增加成长值
        addAmount(rule.getId(), parentId, type, rule.getType() * rule.getAmount(), rule.getRuleName());
    }

    private boolean meetTheRules(Integer ruleId, String limitRule, Integer companyId) {
        boolean result = true;
        // 没设置规则就是符合规则
        if (StringUtils.isBlank(limitRule)) {
            return result;
        }

        JSONObject jsonLimit = JSON.parseObject(limitRule);
        // 如果有每日最大值限制，判断一下没有达到最大值
        if (jsonLimit.containsKey("max_amount_a_day")) {
            Integer maxAmountADay = jsonLimit.getInteger("max_amount_a_day");
            result = meetMaxAmountADay(ruleId, maxAmountADay, companyId);
            logger.info("parentId {} meet max amount a day rule {}", companyId, result);
        }
        // 如果有总的获取次数限制
        if (result && jsonLimit.containsKey("max_count")) {
            Integer maxCount = jsonLimit.getInteger("max_count");
            result = meetMaxCount(ruleId, maxCount, companyId);
            logger.info("parentId {} meet max count rule {}", companyId, result);
        }
        return result;
    }

    /**
     * 符合最大领取数量
     */
    private boolean meetMaxAmountADay(Integer ruleId, Integer maxAmountADay, Integer companyId) {
        if (maxAmountADay == null) {
            return true;
        }
        int sum = levelRecordMapper.selectSumAmountToday(ruleId, companyId);
        return sum < maxAmountADay;
    }

    /**
     * 符合发送领取次数
     */
    private boolean meetMaxCount(Integer ruleId, Integer maxCount, Integer companyId) {
        if (maxCount == null) {
            return true;
        }
        int count = levelRecordMapper.selectCompanyCount(ruleId, companyId);
        return count < maxCount;
    }

}
